
/**
 * 文字左上角为（0，0），向右为正，向下为正
 */

import * as THREE from 'three';
import TWEEN from '../../../node_modules/three/examples/jsm/libs/tween.module.js';

export default class textLabel extends THREE.Sprite {
  constructor(
    txt = 'Label',
    x = 0,
    y = 0,
    color = '#fff',
    fontSize = 24,
    bold = false,
    shadow = false,
    uiCamera1
  ) {
    super()
    this.scaleAspect = window.innerHeight / window.innerWidth / (750 / 1334);
    this.x = x;
    this.y = y + this.getPaddingTop();
    this.width = 0;
    this.height = 0;
    this.txt = txt;
    this.color = color;
    this.fontSize = fontSize;
    this.bold = bold;
    this.shadow = shadow;
    this.uiCamera1=uiCamera1;
    this.radio = window.devicePixelRatio / 2;
    // 设置原点默认是0 1 中心点0.5 0.5 用于控制Label范围rect
    this.origin = new THREE.Vector2(0, 1);
    this.initCanvas();
    this.resetMaterial();
    this.drawCanvas();
    this.setPosition(x, y);
    this.opacity={v:0}; // 初始透明度为0
    this.newPos={x:x,y:y}//移动目标位置
  }
  
  getFont(size, bold = false) {
    let ahead = bold ? 'bold' : '';
    let fontFamily='Arial,Microsoft YaHei,黑体,宋体,sans-serif';
    return `${ahead} ${size}px ${fontFamily}`;
  }

  /**
   *设计稿横坐标转屏幕坐标
  * @param {number} value
  * @returns 屏幕横坐标
  */
  getScreenX(value) {
    return (value * window.innerWidth) / 1334;
  }

  /**
   *设计稿纵坐标转屏幕坐标
  * @param {number} value
  * @param {boolean} scaleHeight 是否缩放到高度铺满，大于16:9会被拉伸
  * @returns 屏幕纵坐标
  */
  getScreenY(value, scaleHeight = false) {
    if (scaleHeight) {
      return (value * window.innerHeight) / 750;
    }
    return (value * window.innerHeight) / 750 / this.scaleAspect;
  }

  getPaddingTop(isCenter = true) {
    return isCenter ? (750 * (this.scaleAspect - 1)) / 2 : 0;
  }

  initCanvas() {
    this.canvas = document.createElement('canvas');
    this.ctx = this.canvas.getContext('2d');
    this.caclLabelSize()
    this.canvas.width = this.width * this.radio
    this.canvas.height = this.height * this.radio
    //console.log('----initCanvas---- this.width this.height this.radio=',this.width,this.height,this.radio)
  }

  resetCanvas() {
    this.caclLabelSize()
    this.canvas.width = this.width * this.radio
    this.canvas.height = this.height * this.radio
    
  }

  resetMaterial() {
    this.texture = new THREE.CanvasTexture(this.canvas);
    this.texture.minFilter = this.texture.magFilter = THREE.LinearFilter;
    this.material.map = this.texture;
    //this.material.transparent=true; 
    //this.material.opacity=0;//所有文字刚加载时不显示，要显示时调用fadeIn
  }

  removeMe(){
    this.removeFromParent (); //淡出之后删除
  }

  resetOpacity(opacity1){
    this.material.opacity=opacity1
  }

  // 创建淡入动画
  fadeIn(callBack){
     new TWEEN.Tween(this.opacity)
      .to( {v:1} , 2000) // 2秒内透明度从0变为1
      .onUpdate(() => {
        this.material.opacity = this.opacity.v; // 更新材质透明度
      })
      .onComplete(() => {
        if(callBack){callBack();}
      })
      .start();
  }
  // 创建淡出动画
  fadeOut(callBack){
    new TWEEN.Tween(this.opacity)
    .to( {v:0} , 2000) // 2秒内透明度从1变为0
    .onUpdate(() => {
      this.material.opacity = this.opacity.v; // 更新材质透明度
    })
    .onComplete(() => {
      if(callBack){callBack();}
    })
    .start();
  }

  //移动
  moveTo(tox,toy,callBack){
    new TWEEN.Tween(this.newPos)
    .to( {x:tox,y:toy} , 3000) // 2秒内透明度从1变为0
    .onUpdate(() => {
      //console.log(this.newPos.x, this.newPos.y)
      this.x = this.newPos.x
      this.y = this.newPos.y
      this.setPosition(this.x, this.y);
    })
    .onComplete(() => {
      if(callBack){callBack();}
    })
    .start();
  }

  drawCanvas() {
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
    //文字需要背景色时，加入下面两句
    // this.ctx.fillStyle="#ff0000";
    // this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height);
    this.ctx.font = this.getFont(this.fontSize * this.radio, this.bold)
    this.ctx.fillStyle = this.color
    if (this.shadow) {
      this.ctx.shadowColor = '#000000'
      this.ctx.shadowBlur = 10
    }
    this.ctx.textBaseline = 'top'
    this.ctx.fillText(this.txt, 0, 0)
    this.texture.needsUpdate = true
  }

  setTxt(txt) {
    this.txt = txt
    this.resetCanvas()
    this.drawCanvas()
  }

  setPosition(x, y) {
    let center = this.getCenterPoint(x, y)
    let p = this.convertToScenePosition(center.x, center.y)
    this.scale.set(this.getScreenX(this.width), this.getScreenY(this.height), 1)
    this.position.set(p.x, p.y, 10)
  }

  setOriginPoint(x, y) {
    // 设置原点默认是0 1 中心点0.5 0.5
    // 用于控制精灵范围rect
    this.origin = new THREE.Vector2(x, y)
    this.setPosition(this.x, this.y)
  }

  setCenterPoint(x, y) {
    // 设置锚点默认是0.5 05 中心点0.5 0.5
    // 用于控制精灵变换参照点
    this.center = new THREE.Vector2(x, y)
    this.setPosition(this.x, this.y)
  }

  getCenterPoint() {
    let p = {
      x: this.x + (0.5 - this.origin.x) * this.width,
      y: this.y + (this.origin.y - 0.5) * this.height,
    }
    return {
      x: p.x + (0.5 - this.center.x) * this.width,
      y: p.y + (0.5 - this.center.y) * this.height,
    }
  }

  // 返回设计稿范围
  getRect() {
    return {
      top: this.y - (1 - this.origin.y) * this.height,
      left: this.x - this.origin.x * this.width,
      right: this.x + (1 - this.origin.x) * this.width,
      bottom: this.y + this.origin.y * this.height,
    }
  }

  // 传入设计稿(x:0, y:0)坐标，左上角为0,0，返回UI场景中坐标
  convertToScenePosition(x, y) {
    x = this.getScreenX(x)
    y = this.getScreenY(y)
    let displayPos = {
      x: (x / window.innerWidth) * 2 - 1,
      y: -(y / window.innerHeight) * 2 + 1,
    }
    let vector = new THREE.Vector3(displayPos.x, displayPos.y, 1)
    vector.unproject(this.uiCamera1)
    return vector
  }

  caclLabelSize() {
    this.ctx.font = this.getFont(this.fontSize, this.bold)
    this.ctx.fillStyle = this.color
    this.ctx.textBaseline = 'top'
    this.width = this.ctx.measureText(this.txt).width + 5
    this.height = this.fontSize
  }
  
}
